package com.mlnx.bluwifi.tp;

import com.mlnx.mptp.exception.InvalidPacketException;
import com.mlnx.mptp.mptp.MpPacket;
import com.mlnx.mptp.mptp.VersionManager;
import com.mlnx.mptp.mptp.head.Header;
import com.mlnx.tp.base.utils.ByteBuffUtils;
import com.mlnx.tp.base.utils.ByteUtils;
import com.mlnx.tp.base.utils.LogLevelInfo;
import com.mlnx.tp.base.utils.LogUtils;
import io.netty.util.ReferenceCountUtil;

import java.nio.ByteBuffer;

/**
 * 蓝牙心电包
 *
 * @author zzb
 * @create 2020/8/12 10:32
 */
public class BlueEcgPacket implements Packet {



    enum State {
        HEAD, VERSION, LEN, CONTANT
    }
    private State state = State.HEAD;
    private int matchHeadIndex;
    private int length;
    private ByteBuffer packetBuff;
    public BlueEcgPacket() {
        packetBuff = ByteBuffer.allocate(10000);
        packetBuff.flip();
    }
    @Override
    public void decode(byte[] bytes, int len) {

        ByteBuffUtils.addBytes(packetBuff, bytes, len);
        switch (state) {
            case HEAD:
                if (matchHead(packetBuff)) {
                    state = State.VERSION;
                } else {
                    break;
                }
            case VERSION:

                if (packetBuff.remaining()>0) {
                    byte code = packetBuff.get();
                    if (VersionManager.isSupport(code)) {
                        state = State.LEN;
                    } else {
                        int mainCode = (code >> 4) & 0x0000000f;
                        int subCode = code & 0x0f;

                        LogUtils.e(String
                                .format("不支持的协议版本%d.%d", mainCode, subCode));
                        state = State.HEAD;
                        break;
                    }
                } else {
                    break;
                }
            case LEN:
                length = getPacketLength(packetBuff);
                     LogUtils.d(length+"=====");
                if (length > Header.MaxLength) {
                    LogUtils.w(String.format("数据包长度过长  实际包长度为%d", length));
                    state = State.HEAD;
                    break;
                } else if (length >= 0) {
                    state = State.CONTANT;
                    LogUtils.mpFrame("frame len:" + length);
                }  else {
                    break;
                }
            case CONTANT:
                if (packetBuff.remaining()>6000) {
                    MpPacket mpPacket = new MpPacket();
                    try {
                        if (LogLevelInfo.getInstance().isOpenFrameLog()) {
                            LogUtils.mpFrame("recive  contant:" );
                        }

                        mpPacket.decode(packetBuff);
                    } catch (InvalidPacketException e) {
                        LogUtils.e("receive Exception:",e);
                    } finally {
                        ReferenceCountUtil.release(packetBuff);
                    }

                    state = State.HEAD;
                }
                break;
            default:
        }
    }

    private boolean matchHead(ByteBuffer buf) {
        while (buf.remaining() > 0) {
            if (matchHeadIndex == Header.Heads.length) {
                matchHeadIndex = 0;
                return true;
            }
            byte b = buf.get();
            if (b == Header.Heads[matchHeadIndex]) {
                matchHeadIndex++;
            } else if (b == Header.Heads[0]) {
                matchHeadIndex = 1;
            } else {
                matchHeadIndex = 0;
            }
        }
        return false;

    }

    private int getPacketLength(ByteBuffer buf) {
        if (buf.remaining()>0) {
            byte[] dst = new byte[Header.LengthByteSize];
            buf.get(dst);
            int length = ByteUtils.bytesToInt(dst, Header.LengthByteSize);

            return length;
        } else {
            return -1;
        }
    }
}
